#include "MySqlConnPool.h"
#include "BlockingQueue.hpp"
#include "ConnObject.h"
#include "SqlOperation.h"
#include "QueryCallback.h"

std::unordered_map<std::string,MySqlConnPool*> MySqlConnPool::m_pools_map;

MySqlConnPool::MySqlConnPool(const std::string &db):m_mysql_db(db)
{
}

MySqlConnPool::~MySqlConnPool()
{
    if (m_task_queue != nullptr){
        m_task_queue->Cancel();
    }
    for(auto conn : m_vec_conn){
        delete conn;
        conn = nullptr;
    }
    if (m_task_queue != nullptr){
        delete m_task_queue;
        m_task_queue = nullptr;
    }
    m_pools_map.clear();
}

MySqlConnPool *MySqlConnPool::GetInstance(const std::string &db)
{
    auto it = m_pools_map.find(db);
    if (it == m_pools_map.end()){
        m_pools_map[db] = new MySqlConnPool(db);
    }
    return m_pools_map[db];
}

void MySqlConnPool::InitConnPool(const std::string &url, int sizepool)
{
    m_task_queue = new BlockingQueuePro<SqlOperation*>();
    for (size_t i = 0; i < sizepool; i++)
    {
        ConnObject* obj = new ConnObject(m_mysql_db,url,*m_task_queue);
        obj->Open();
        m_vec_conn.push_back(obj);
    }
}

QueryCallback MySqlConnPool::PushQuery(const std::string &sql, std::function<void(std::unique_ptr<sql::ResultSet>)> &&cb)
{
    SqlOperation *sqlOpr = new SqlOperation(sql);
    auto future = sqlOpr->GetFuture();
    m_task_queue->Push(sqlOpr);
    return QueryCallback(std::move(future),std::move(cb));
}
